<?php
/**
 * 模型管理
 * @author 银杏ERP
 * @version 1.0
 * @since 2025-03-28
 * @copyright 2025 红河州银杏科技有限公司
 * @license http://www.hhyx.xyz
 * @developer Lhf
 */
namespace app\admin\controller\yxerp;

use think\facade\Db;
use think\facade\Config;
use app\common\controller\Backend;
class AIModel extends Backend
{
    protected object $model;
    public function initialize(): void
    {
        parent::initialize();
        $this->model = new \app\admin\model\yxerp\AiModel();
    }
    /**
     * 获取AI模型列表
     */
    public function getModelList()
    {
        $models = Db::name('yxerp_ai_models')
            ->field('id, name, type, provider, endpoint, api_key, model_name, params, is_active, create_time, update_time')
            ->order('create_time DESC, id DESC')
            ->select()
            ->toArray();
        
        return json(['code' => 1, 'msg' => '获取成功', 'data' => $models]);
    }
    
    /**
     * 获取模型详情
     */
    public function getModel()
    {
        $id = request()->param('id/d', 0);
        if (empty($id)) {
            return json(['code' => 0, 'msg' => '参数错误']);
        }
        
        $model = Db::name('yxerp_ai_models')->where('id', $id)->find();
        if (!$model) {
            return json(['code' => 0, 'msg' => '模型不存在']);
        }
        
        // 解密API密钥
        if (!empty($model['api_key'])) {
            $model['api_key'] = $this->decryptApiKey($model['api_key']);
        }
        
        // 解析JSON参数
        if (!empty($model['params'])) {
            $model['params'] = json_decode($model['params'], true);
        } else {
            $model['params'] = [];
        }
        
        return json(['code' => 1, 'msg' => '获取成功', 'data' => $model]);
    }
    
    /**
     * 添加/编辑模型
     */
    public function saveModel()
    {
        $data = $this->request->param();
        $id = isset($data['id']) ? intval($data['id']) : 0;
        // 校验必填字段
        if (empty($data['name']) || empty($data['provider']) || empty($data['type'])) {
            return json(['code' => 0, 'msg' => '请填写模型名称、提供商和模型类型']);
        }
        
        // 检查模型名称是否重复
        $exists = $this->model
            ->where('name', $data['name'])
            ->where('id', '<>', $id)
            ->find();
        
        if ($exists) {
            return json(['code' => 0, 'msg' => '模型名称已存在']);
        }
        
        
        // 处理参数
        if (isset($data['params']) && is_array($data['params'])) {
            $data['params'] = json_encode($data['params']);
        } else {
            $data['params'] = '';
        }
        
        if ($id > 0) {
            $result =$this->model->where('id', $id)->update($data);
            $msg = '更新成功';
        } else {
            $result = $this->model->insert($data);
            $msg = '添加成功';
        }
        
        if ($result !== false) {
            return json(['code' => 1, 'msg' => $msg]);
        } else {
            return json(['code' => 0, 'msg' => $id > 0 ? '更新失败' : '添加失败']);
        }
    }
    
    /**
     * 删除模型
     */
    public function deleteModel()
    {
        $id = request()->param('id/d', 0);
        if (empty($id)) {
            return json(['code' => 0, 'msg' => '参数错误']);
        }
        
        // 检查模型是否在使用中
        $used = Db::name('yxerp_ai_conversations')->where('model_id', $id)->find();
        if ($used) {
            return json(['code' => 0, 'msg' => '该模型正在被聊天会话使用，无法删除']);
        }
        
        $result = Db::name('yxerp_ai_models')->where('id', $id)->delete();
        if ($result) {
            return json(['code' => 1, 'msg' => '删除成功']);
        } else {
            return json(['code' => 0, 'msg' => '删除失败']);
        }
    }
    
    /**
     * 设置默认模型
     */
    public function setDefaultModel()
    {
        $id = request()->param('id/d', 0);
        if (empty($id)) {
            return json(['code' => 0, 'msg' => '参数错误']);
        }
        
        $model = Db::name('yxerp_ai_models')->where('id', $id)->find();
        if (!$model) {
            return json(['code' => 0, 'msg' => '模型不存在']);
        }
        
        // 先将同类型的其他模型设置为非默认
        Db::name('yxerp_ai_models')
            ->where('model_type', $model['model_type'])
            ->update(['is_default' => 0]);
        
        // 设置为默认
        $result = Db::name('yxerp_ai_models')
            ->where('id', $id)
            ->update(['is_default' => 1, 'update_time' => date('Y-m-d H:i:s')]);
        
        if ($result) {
            return json(['code' => 1, 'msg' => '设置成功']);
        } else {
            return json(['code' => 0, 'msg' => '设置失败']);
        }
    }
    
   /**
 * 测试模型连接
 */
public function testModel()
{
    $data = request()->post();
    $type = $data['type'] ?? '';
    $provider = $data['provider'] ?? '';
    $endpoint = $data['endpoint'] ?? '';
    $apiKey = $data['api_key'] ?? '';
    $modelName = $data['model_name'] ?? '';
    
    // 根据模型类型进行不同测试
    if ($type == 'local') {
        // 测试Ollama连接
        try {
            $client = new \GuzzleHttp\Client();
            $response = $client->get($endpoint.'/api/tags');
            return json(['code' => 1, 'msg' => '连接成功', 'data' => json_decode($response->getBody(), true)]);
        } catch (\Exception $e) {
            return json(['code' => 0, 'msg' => '连接失败：'.$e->getMessage()]);
        }
    } else {
        // 测试远程API连接
        try {
            // 根据不同提供商构建测试请求
            $testResult = $this->testRemoteProvider($provider, $endpoint, $apiKey, $modelName);
            return json(['code' => 1, 'msg' => '连接成功', 'data' => $testResult]);
        } catch (\Exception $e) {
            return json(['code' => 0, 'msg' => '连接失败：'.$e->getMessage()]);
        }
    }
}

    
    /**
     * 测试OpenAI接口
     */
    private function testOpenAI($endpoint, $apiKey, $modelType)
    {
        $curl = curl_init();
        $headers = [
            'Content-Type: application/json',
            'Authorization: Bearer ' . $apiKey
        ];
        
        // 根据模型类型确定API路径
        $apiPath = '/v1/chat/completions';
        $data = [
            'model' => 'gpt-3.5-turbo',
            'messages' => [
                ['role' => 'user', 'content' => 'Hello, this is a test message.']
            ],
            'max_tokens' => 50
        ];
        
        if ($modelType === 'image') {
            $apiPath = '/v1/images/generations';
            $data = [
                'prompt' => 'A test image of a blue sky',
                'n' => 1,
                'size' => '256x256'
            ];
        }
        
        curl_setopt_array($curl, [
            CURLOPT_URL => $endpoint . $apiPath,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => $headers,
        ]);
        
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        curl_close($curl);
        
        if ($error) {
            throw new \Exception('CURL Error: ' . $error);
        }
        
        if ($httpCode >= 400) {
            $responseData = json_decode($response, true);
            $errorMsg = isset($responseData['error']['message']) 
                ? $responseData['error']['message'] 
                : 'API Error: HTTP ' . $httpCode;
            throw new \Exception($errorMsg);
        }
        
        return json_decode($response, true);
    }
    
    /**
     * 测试Azure OpenAI接口
     */
    private function testAzure($endpoint, $apiKey, $modelType)
    {
        // Azure OpenAI测试逻辑，类似OpenAI但API路径和认证方式不同
        $curl = curl_init();
        $headers = [
            'Content-Type: application/json',
            'api-key: ' . $apiKey
        ];
        
        // Azure需要在URL中指定部署名称，这里假设部署名称为"gpt35"
        $apiPath = '/openai/deployments/gpt35/chat/completions?api-version=2023-05-15';
        $data = [
            'messages' => [
                ['role' => 'user', 'content' => 'Hello, this is a test message.']
            ],
            'max_tokens' => 50
        ];
        
        curl_setopt_array($curl, [
            CURLOPT_URL => $endpoint . $apiPath,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => $headers,
        ]);
        
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        curl_close($curl);
        
        if ($error) {
            throw new \Exception('CURL Error: ' . $error);
        }
        
        if ($httpCode >= 400) {
            $responseData = json_decode($response, true);
            $errorMsg = isset($responseData['error']['message']) 
                ? $responseData['error']['message'] 
                : 'API Error: HTTP ' . $httpCode;
            throw new \Exception($errorMsg);
        }
        
        return json_decode($response, true);
    }
    
    /**
     * 测试Anthropic接口
     */
    private function testAnthropic($endpoint, $apiKey, $modelType)
    {
        $curl = curl_init();
        $headers = [
            'Content-Type: application/json',
            'x-api-key: ' . $apiKey,
            'anthropic-version: 2023-06-01'
        ];
        
        $data = [
            'model' => 'claude-2',
            'prompt' => "\n\nHuman: Hello, this is a test message.\n\nAssistant:",
            'max_tokens_to_sample' => 50
        ];
        
        curl_setopt_array($curl, [
            CURLOPT_URL => $endpoint . '/v1/complete',
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS => json_encode($data),
            CURLOPT_HTTPHEADER => $headers,
        ]);
        
        $response = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $error = curl_error($curl);
        curl_close($curl);
        
        if ($error) {
            throw new \Exception('CURL Error: ' . $error);
        }
        
        if ($httpCode >= 400) {
            $responseData = json_decode($response, true);
            $errorMsg = isset($responseData['error']['message']) 
                ? $responseData['error']['message'] 
                : 'API Error: HTTP ' . $httpCode;
            throw new \Exception($errorMsg);
        }
        
        return json_decode($response, true);
    }
    
    /**
     * 加密API密钥
     */
    private function encryptApiKey($key)
    {
        return openssl_encrypt(
            $key,
            'AES-256-CBC',
            Config::get('app.app_key'),
            0,
            substr(Config::get('app.app_key'), 0, 16)
        );
    }
    
    /**
     * 解密API密钥
     */
    private function decryptApiKey($encrypted)
    {
        return openssl_decrypt(
            $encrypted,
            'AES-256-CBC',
            Config::get('app.app_key'),
            0,
            substr(Config::get('app.app_key'), 0, 16)
        );
    }
} 